using System;
using System.Linq;
using System.Net.Mail;
using System.Web.Mvc;
using System.Web.Security;
using MvcMembership;
using Website.Models;
using System.Configuration;
using Website.Models.UserAdministration;
using System.Collections.Generic;
using System.Globalization;
using System.Security.Principal;
using System.Web;
using System.Web.UI;
using Website.Controllers;

namespace Website.Controllers
{
    [Authorize(Roles = "Administrator")]
	public class UserAdministrationController : Controller
	{
		private const int PageSize = 10;
		private const string ResetPasswordBody = "Your new password is: ";
		private const string ResetPasswordFromAddress = "from@domain.com";
		private const string ResetPasswordSubject = "Your New Password";
		private readonly IRolesService _rolesService;
		private readonly ISmtpClient _smtpClient;
		private readonly IUserService _userService;
		private readonly IPasswordService _passwordService;

		public UserAdministrationController()
			: this(
				new AspNetMembershipProviderWrapper(Membership.Provider),
				new AspNetMembershipProviderWrapper(Membership.Provider),
				new AspNetRoleProviderWrapper(Roles.Provider),
				new SmtpClientProxy(new SmtpClient()))
		{
		}

		public UserAdministrationController(
			IUserService userService,
			IPasswordService passwordService,
			IRolesService rolesService,
			ISmtpClient smtpClient)
		{
			_userService = userService;
			_passwordService = passwordService;
			_rolesService = rolesService;
			_smtpClient = smtpClient;
		}

		public ViewResult Index(int? index)
		{
			return View(new IndexViewModel
			            	{
								Users = _userService.FindAll(index ?? 0, PageSize),
			            		Roles = _rolesService.FindAll()
			            	});
		}

        public ViewResult RolesMain(int? index)
        {
            return View(new IndexViewModel
            {
                Users = _userService.FindAll(index ?? 0, PageSize),
                Roles = _rolesService.FindAll()
            });
        }

		[AcceptVerbs(HttpVerbs.Post)]
		public RedirectToRouteResult CreateRole(string id)
		{
			_rolesService.Create(id);
			return RedirectToAction("Index");
		}

		[AcceptVerbs(HttpVerbs.Post)]
		public RedirectToRouteResult DeleteRole(string id)
		{
			_rolesService.Delete(id);
			return RedirectToAction("Index");
		}

		public ViewResult Role(string id)
		{
			return View(new RoleViewModel
			            	{
			            		Role = id,
								Users = _rolesService.FindUserNamesByRole(id).Select(username => _userService.Get(username))
			            	});
		}


		public ViewResult Details(Guid id)
		{
			var user = _userService.Get(id);
			var userRoles = _rolesService.FindByUser(user);
			return View(new DetailsViewModel
			            	{
			            		DisplayName = user.UserName,
			            		User = user,
			            		Roles = _rolesService.FindAll().ToDictionary(role=> role, role=> userRoles.Contains(role)),
			            		Status = user.IsOnline
			            		         	? DetailsViewModel.StatusEnum.Online
			            		         	: !user.IsApproved
			            		         	  	? DetailsViewModel.StatusEnum.Unapproved
			            		         	  	: user.IsLockedOut
			            		         	  	  	? DetailsViewModel.StatusEnum.LockedOut
			            		         	  	  	: DetailsViewModel.StatusEnum.Offline
			            	});
		}

		[AcceptVerbs(HttpVerbs.Post)]
		public RedirectToRouteResult Details(Guid id,
		                            [Bind(Prefix = "User.Email")] string email,
		                            [Bind(Prefix = "User.Comment")] string comment)
		{
			var user = _userService.Get(id);
			user.Email = email;
			user.Comment = comment;
			_userService.Update(user);
			return RedirectToAction("Details", new {id});
		}

		[AcceptVerbs(HttpVerbs.Post)]
		public RedirectToRouteResult DeleteUser(Guid id)
		{
            if(Roles.IsUserInRole(_userService.Get(id).UserName, "Administrator"))
                Roles.RemoveUserFromRole(_userService.Get(id).UserName, "Administrator");
            if(Roles.IsUserInRole(_userService.Get(id).UserName, "HiringSpecialist"))
                Roles.RemoveUserFromRole(_userService.Get(id).UserName, "HiringSpecialist");
            if(Roles.IsUserInRole(_userService.Get(id).UserName, "HiringManager"))
                Roles.RemoveUserFromRole(_userService.Get(id).UserName, "HiringManager");
            if(Roles.IsUserInRole(_userService.Get(id).UserName, "Applicant"))
                Roles.RemoveUserFromRole(_userService.Get(id).UserName, "Applicant");
            if (Roles.IsUserInRole(_userService.Get(id).UserName, "StaffingExpert"))
                Roles.RemoveUserFromRole(_userService.Get(id).UserName, "StaffingExpert");
			_userService.Delete(_userService.Get(id));
			return RedirectToAction("Index");
		}

		[AcceptVerbs(HttpVerbs.Post)]
		public RedirectToRouteResult ChangeApproval(Guid id, bool isApproved)
		{
			var user = _userService.Get(id);
			user.IsApproved = isApproved;
			_userService.Update(user);
			return RedirectToAction("Details", new {id});
		}

		[AcceptVerbs(HttpVerbs.Post)]
		public RedirectToRouteResult Unlock(Guid id)
		{
			_passwordService.Unlock(_userService.Get(id));
			return RedirectToAction("Details", new {id});
		}

		[AcceptVerbs(HttpVerbs.Post)]
		public RedirectToRouteResult ResetPassword(Guid id, string answer)
		{
			var user = _userService.Get(id);
			var newPassword = _passwordService.ResetPassword(user, answer);

			var body = ResetPasswordBody + newPassword;
			_smtpClient.Send(new MailMessage(ResetPasswordFromAddress, user.Email, ResetPasswordSubject, body));

			return RedirectToAction("Details", new {id});
		}

		[AcceptVerbs(HttpVerbs.Post)]
		public RedirectToRouteResult AddToRole(Guid id, string role)
		{
			_rolesService.AddToRole(_userService.Get(id), role);
			return RedirectToAction("Details", new { id });
		}

		[AcceptVerbs(HttpVerbs.Post)]
		public RedirectToRouteResult RemoveFromRole(Guid id, string role)
		{
			_rolesService.RemoveFromRole(_userService.Get(id), role);
			return RedirectToAction("Details", new { id });
		}

        public ActionResult CreateUser()
        {
            return View();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult CreateUser(string userName, string email, string password, string confirmPassword, string role)
        {
            AccountMembershipService MembershipService = new AccountMembershipService();
           
            // Attempt to register the user
            MembershipCreateStatus createStatus = MembershipService.CreateUser(userName, password, email);
            if (createStatus == MembershipCreateStatus.Success)
            {
                switch (role)
                {
                    case "HiringManager":
                        Roles.AddUserToRole(userName, "HiringManager");
                        break;
                    case "HiringSpecialist":
                        Roles.AddUserToRole(userName, "HiringSpecialist");
                        break;
                    case "Administrator":
                        Roles.AddUserToRole(userName, "Administrator");
                        break;
                    case "StaffingExpert":
                        Roles.AddUserToRole(userName, "StaffingExpert");
                        break;
                    default:
                        Roles.AddUserToRole(userName, "Applicant");
                        break;
                }

            }
            else
            {

            }
            // If we got this far, something failed, redisplay form
            return RedirectToAction("Index");
        }

        /// <summary>
        /// Redirect the user to a specific URL, as specified in the web.config, depending on their role.
        /// If a user belongs to multiple roles, the first matching role in the web.config is used.
        /// Prioritize the role list by listing higher-level roles at the top.
        /// </summary>
        /// <param name="username">Username to check the roles for</param>
        private void RedirectLogin(string username)
        {
            WebSite.LoginRedirectByRoleSection roleRedirectSection = (WebSite.LoginRedirectByRoleSection)ConfigurationManager.GetSection("loginRedirectByRole");
            foreach (WebSite.RoleRedirect roleRedirect in roleRedirectSection.RoleRedirects)
            {
                if (Roles.IsUserInRole(username, roleRedirect.Role))
                {
                    Response.Redirect(roleRedirect.Url);
                }
            }
        }
	}
}